
#include "core/graph/ImageFx.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize2.h"

void Graph::ImageFx::InitHD(int w, int h, int nr, int hdr)
{
	m_HD.m_Width = w;
	m_HD.m_Height = h;
	m_HD.m_NrComponent = nr;
	m_HD.m_Hdr = hdr;
};

void Graph::ImageFx::AllocData() 
{
	Free();
	m_Data = new unsigned char[m_HD.DataSize()];
};


void Graph::ImageFx::Write(const std::string &path) const

{
	std::ofstream ofs(path, std::ios::binary);

	Write(ofs);
	ofs.flush();
	ofs.close();

}

void Graph::ImageFx::Write(std::ofstream& ofs) const
{
	ofs.write((const char*)&m_HD, sizeof(m_HD));
	ofs.write((const char*)m_Data, m_HD.DataSize());

}

void Graph::ImageFx::Read(const std::string& path)
{
	std::ifstream ifs(path, std::ios::binary);
	Read(ifs);
	ifs.close();
}

void Graph::ImageFx::Read(std::ifstream& ifs)
{
	ifs.read((char*)&m_HD, sizeof(m_HD));
	
	AllocData();
	ifs.read((char*)m_Data, m_HD.DataSize());
	
}

void Graph::ImageFx::WriteBMP(const std::string& path) const
{
	stbi_write_bmp(path.c_str(), m_HD.m_Width, m_HD.m_Height, m_HD.m_NrComponent, m_Data);
}

void *Graph::ImageFx::GetData() const
{
	return m_Data;
}

void Graph::ImageFx::Free()
{
	if(m_Data)
	{
		free(m_Data);
		m_Data = 0;

	}else
	{
		std::cout << "failed free null data" << std::endl;
	}
}

void Graph::ImageFx::Resize(int w, int h)
{
	m_HD.m_Width = w;
	m_HD.m_Height = h;
}

Graph::ImageFx::ImageFx(const Desc &desc)
	: m_Desc(desc)
{
	m_Avail = Init();
}

bool Graph::ImageFx::Init()
{
	auto desc = m_Desc;
	m_HD.m_Hdr = desc.m_hdr;
	if (desc.m_hdr)
	{
		m_Data = stbi_loadf(desc.m_Path.c_str(), &m_HD.m_Width, &m_HD.m_Height, &m_HD.m_NrComponent, desc.m_ReqComponent);
	}
	else
	{
		m_Data = stbi_load(desc.m_Path.c_str(), &m_HD.m_Width, &m_HD.m_Height, &m_HD.m_NrComponent, desc.m_ReqComponent);
	};

	if (desc.m_ReqComponent > 0 && desc.m_ReqComponent <= 4)
	{
		m_HD.m_NrComponent = desc.m_ReqComponent;
	};
	return true;
}
